package com.partsoft.webs.spring;

import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;

import com.partsoft.utils.Assert;
import com.partsoft.utils.ClassUtils;
import com.partsoft.utils.StringUtils;

/**
 * 通过静态类与静态方法获取Web上下文
 * 
 * @author neeker
 */
public class ContextStaticResolveServlet extends HttpServlet {

	private static final long serialVersionUID = 5318615178409752416L;

	public void init() throws ServletException {
		ServletConfig sc = getServletConfig();
		if (getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
			throw new IllegalStateException("根应用上下文已经设置过!");
		}
		initWebApplicationContext(sc);
	}

	protected void initWebApplicationContext(ServletConfig sc) {
		WebApplicationContext webAppContext = null;
		String resolveClazzName = sc.getInitParameter("resolveClass");
		String resolveStaticMethodName = sc.getInitParameter("staticMethod");
		String contextWebAppContext = sc.getInitParameter("webApplicationContext");
		if (!StringUtils.hasText(contextWebAppContext)) {
			contextWebAppContext = "webApplicationContext";
		}

		Assert.hasText(resolveClazzName, "必须设置resolveClass参数");
		Assert.hasText(resolveStaticMethodName, "必须设置staticMethod参数");

		Class<?> resolveClazz = null;

		try {
			resolveClazz = ClassUtils.forName(resolveClazzName);
		} catch (Throwable e) {
			throw new IllegalStateException(String.format("无法找到类(%s)", resolveClazzName));
		}

		Method resolveStaticMethod = ClassUtils.getMethodIfAvailable(resolveClazz, resolveStaticMethodName,
				new Class[0]);
		Assert.notNull(resolveStaticMethod,
				String.format("无法找到类(%s)的静态方法(%s)", resolveClazz.getName(), resolveStaticMethodName));

		try {
			ApplicationContext rootAppContext = (ApplicationContext) resolveStaticMethod.invoke(null);
			webAppContext = rootAppContext.getBean(contextWebAppContext, WebApplicationContext.class);
		} catch (Throwable e) {
			throw new IllegalStateException(String.format("无法通过类(%s)的静态方法(%s)获取根上下文对象(%s)", resolveClazz.getName(),
					resolveStaticMethodName, contextWebAppContext));
		}
		getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webAppContext);
	}

	/**
	 * Servlet销毁时的动作
	 */
	public void destroy() {
		ServletContext sc = getServletContext();
		sc.removeAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
	}

	public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
		getServletContext().log(
				"Attempt to call service method on DitsContextLoaderServlet as [" + request.getRequestURI()
						+ "] was ignored");
		response.sendError(HttpServletResponse.SC_BAD_REQUEST);
	}

	public String getServletInfo() {
		return "ContextLoaderServlet for Servlet API 2.3 "
				+ "(deprecated in favor of ContextLoaderListener for Servlet API 2.4)";
	}
}
